var Rules = {
	ArmorReductionPercent: function(armor) {
		//var reduction = Math.sqrt(10*armor)/100;
		var reduction = armor / 1000;
		return reduction;
	},
	Counter: function(caster, target) {
		var caster_ability = caster.CastingAbility;
		var target_ability = target.CastingAbility;
		if ( !caster_ability || !target_ability ) return null;
		var ability_throw = caster_ability.Saves[target_ability.Name].Throw;
		if ( Math.random() * (11 + ability_throw) > 5 ) return caster_ability.Saves[target_ability.Name].Counter;
		return null;
	},
	ApplyDamage: function(ability) {
		var caster = ability.Caster;
		var target = ability.Caster.Target;
		var damage = ability.Damage + (Math.random() * (ability.Variance * 2) * ability.Damage - (ability.Variance * ability.Damage));
		damage = (caster.ModStats.Power) * damage;
		if ( caster.Enhancements.HasAny('focus') ) {
			damage += damage * .1;
			caster.Enhancements.RemoveStacks({name: 'focus', stacks: 1}); 
		}
		var absorbed = Rules.ArmorReductionPercent(target.ModStats.Armor) * damage;
		var total = damage - absorbed;
		if ( total < 0 ) total = 0;
		target.ApplyDamage(total);
		Log({type: 'Rules.ApplyDamage', total: total, absorbed: absorbed, ability: ability});
	},
	AbilityCanHit: function(ability) {
		var caster = ability.Caster;
		var target = ability.Caster.Target;
		if (
			( // Proper level:
				(ability.CastSame && (
					(caster.HasAny('Jump') && target.HasAny('Jump')) ||
					(caster.HasAny('DoubleJump') && target.HasAny('DoubleJump')) ||
					(
						!target.HasAny('DoubleJump') &&
						!caster.HasAny('DoubleJump') &&
						!target.HasAny('Jump') &&
						!caster.HasAny('Jump') &&
						!target.HasAny('Knockdown')
					)
				)) ||
				(ability.CastDown && (
					(caster.HasAny('DoubleJump') && target.HasAny('Jump')) ||
					(caster.HasAny('Jump') && !target.HasAny('Jump') && !target.HasAny('DoubleJump') && !target.HasAny('Knockdown') ) ||
					(!caster.HasAny('Jump') && !caster.HasAny('DoubleJump') && target.HasAny('Knockdown') )
				)) ||
				(ability.CastUp && (
					(caster.HasAny('Jump') && target.HasAny('DoubleJump')) ||
					(!caster.HasAny('Jump') && !caster.HasAny('DoubleJump') && target.HasAny('Jump') )
				))
			)
			&&
			( // Proper Range
				(ability.CastMelee && (
					!caster.HasAny('Distance') && !caster.HasAny('Distance')
				)) ||
				(ability.CastRange && (
					caster.HasAny('Distance') || caster.HasAny('Distance')
				))
			)
		) {
			return true;
		}
		return false;
	}
};
